{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Generators\n",
    "Generators are a simpler way to create iterators. They use the yield keyword to produce a series of values lazily, which means they generate values on the fly and do not store them in memory."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "def square(n):\n",
    "    for i in range(3):\n",
    "        yield i**2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<generator object square at 0x00000222FFEFF2A0>"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "square(3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\n",
      "1\n",
      "4\n"
     ]
    }
   ],
   "source": [
    "for i in square(3):\n",
    "    print(i)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<generator object square at 0x00000222FFEFE8E0>"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a=square(3)\n",
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "ename": "StopIteration",
     "evalue": "",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mStopIteration\u001b[0m                             Traceback (most recent call last)",
      "Cell \u001b[1;32mIn[10], line 1\u001b[0m\n\u001b[1;32m----> 1\u001b[0m \u001b[38;5;28;43mnext\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43ma\u001b[49m\u001b[43m)\u001b[49m\n",
      "\u001b[1;31mStopIteration\u001b[0m: "
     ]
    }
   ],
   "source": [
    "next(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "def my_generator():\n",
    "    yield 1\n",
    "    yield 2\n",
    "    yield 3"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<generator object my_generator at 0x00000222FFD95DD0>"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "gen=my_generator()\n",
    "gen"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "ename": "StopIteration",
     "evalue": "",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mStopIteration\u001b[0m                             Traceback (most recent call last)",
      "Cell \u001b[1;32mIn[16], line 1\u001b[0m\n\u001b[1;32m----> 1\u001b[0m \u001b[38;5;28;43mnext\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mgen\u001b[49m\u001b[43m)\u001b[49m\n",
      "\u001b[1;31mStopIteration\u001b[0m: "
     ]
    }
   ],
   "source": [
    "next(gen)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "2\n",
      "3\n"
     ]
    }
   ],
   "source": [
    "for val in gen:\n",
    "    print(val)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Practical Example: Reading Large Files\n",
    "Generators are particularly useful for reading large files because they allow you to process one line at a time without loading the entire file into memory."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "### Practical : Reading LArge Files\n",
    "\n",
    "def read_large_file(file_path):\n",
    "    with open(file_path,'r') as file:\n",
    "        for line in file:\n",
    "            yield line"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Smt. Droupadi Murmu was sworn in as the 15th President of India on 25 July, 2022. Previously, she was the Governor of Jharkhand from 2015 to 2021. She has devoted her life to empowering the downtrodden and the marginalised sections and deepening the democratic values.\n",
      "\n",
      "Early Life and Education\n",
      "\n",
      "Born in a Santhali tribal family on 20 June, 1958 at Uparbeda village, Mayurbhanj, Odisha, Smt. Murmu’s early life was marked by hardships and struggle. On completion of primary education from the village school, she went to Bhubaneswar on her own initiative to continue her studies. She earned the degree of Bachelor of Arts from Ramadevi Women’s College, Bhubaneswar and became the first woman from her village to receive college education.\n",
      "\n",
      "Professional Career\n",
      "\n",
      "From 1979 to 1983, Smt. Murmu served as a Junior Assistant in the Irrigation and Power Department, Government of Odisha. Later, she served as an honorary teacher at Sri Aurobindo Integral Education Centre, Rairangpur, from 1994 to 1997.\n",
      "\n",
      "Public Life\n",
      "\n",
      "In 2000, Smt. Murmu was elected from the Rairangpur constituency as a Member of the Legislative Assembly of Odisha and continued to hold the post till 2009, serving two terms. During this period, she served as Minister of State (Independent Charge), Department of Commerce and Transport in the Government of Odisha from March 6, 2000 to August 6, 2002 and as Minister of State (Independent Charge), Department of Fisheries and Animal Resources Development, Government of Odisha from Augu\n"
     ]
    }
   ],
   "source": [
    "file_path='large_file.txt'\n",
    "\n",
    "for line in read_large_file(file_path):\n",
    "    print(line.strip())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Conclusion\n",
    "Iterators and generators are powerful tools in Python for creating and handling sequences of data efficiently. Iterators provide a way to access elements sequentially, while generators allow you to generate items on the fly, making them particularly useful for handling large datasets and infinite sequences. Understanding these concepts will enable you to write more efficient and memory-conscious Python programs."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
